package com.party.notify.wechatNotify.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.party.api.dto.wechat.requst.CustomImage;
import com.party.api.dto.wechat.requst.CustomRequest;
import com.party.api.dto.wechat.requst.CustomText;
import com.party.api.dto.wechat.response.Response;
import com.party.api.dto.wechat.response.UploadTempMediaResponse;
import com.party.api.service.wechat.IWechatService;
import com.party.common.constant.Constant;
import com.party.common.constant.WechatConstant;
import com.party.common.redis.StringJedis;
import com.party.common.utils.DateUtils;
import com.party.common.utils.StringUtils;
import com.party.common.utils.wechat.WechatUtils;
import com.party.core.exception.BusinessException;
import com.party.core.service.wechatPlatform.IWechatOpenMemberService;
import com.party.notify.jms.publisher.service.INotifyPublisherService;
import com.party.notify.wechatNotify.model.TemplateMessage;
import com.party.notify.wechatNotify.model.TemplateParameter;
import com.party.notify.wechatNotify.model.XcxTemplateMessage;
import com.party.notify.wechatNotify.model.XcxTemplateParameter;
import com.party.notify.wechatNotify.service.IWechatNotifyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 微信模板消息推送接口实现
 * Created by wei.li
 *
 * @date 2017/5/17 0017
 * @time 13:52
 */

@Service
public class WechatNotifyService implements IWechatNotifyService {

    protected static Logger logger = LoggerFactory.getLogger(WechatNotifyService.class);

    private static final String ACCESS_TOKEN = "ACCESS_TOKEN";

    @Autowired
    private INotifyPublisherService notifyPublisherService;

    @Autowired
    private IWechatOpenMemberService wechatOpenMemberService;

    @Autowired
    private IWechatService wechatService;
    private static final String REDIS_XCX_FORMID_LIST_KEY = "xcxFormIdListKey";


    @Autowired
    StringJedis stringJedis;

    /**
     * 发送微信模板消息
     * @param url 连接
     * @param requestJsonStr 模板消息请求参数Json字符串
     * @return 发送结果(true/false)
     */
    public boolean send(String url, String requestJsonStr) throws Exception {

        logger.info("微信发送模板消息, 请求报文{}", requestJsonStr);

        JSONObject response = WechatUtils.httpRequest(url, WechatUtils.POST, requestJsonStr);

        logger.info("微信发送模板消息, 返回报文{}", response.toJSONString());

        if (Constant.WECHAT_CODE_SUCCESS.equals(response.get(Constant.WECHAT_ERR_CODE))){
            return true;
        } else {
            Integer errcode = response.get(Constant.WECHAT_ERR_CODE) != null ? (Integer) response.get(Constant.WECHAT_ERR_CODE) : -1;
            String errmsg = response.get("errmsg") != null ? response.get("errmsg").toString() : "";
            Integer subscribeErrorCode = 43004;
            // 43004 需要接收者关注
            // 没有关注的异常可以不用入库，因为这个错误太多了导致没法监控到真正的错误。
            if (subscribeErrorCode.equals(errcode) && errmsg.indexOf("require subscribe") != -1) {
                return false;
            }
            throw new Exception(response.toJSONString());
        }
    }

    /**
     * 发送小程序模板消息
     *
     * @param templateParameter 请求参数对象
     * @return 发送结果(true / false)
     */
    public boolean sendXcxMsg(XcxTemplateParameter templateParameter) {
        String requestJsonStr = JSONObject.toJSONString(templateParameter.getXcxTemplateMessage());
        String memberId = templateParameter.getMemberId();
        String formIdToDay = templateParameter.getFormIdToDay();
        try {
            return this.send(templateParameter.getUrl(), requestJsonStr);
        } catch (Exception e) {
            logger.error("微信小程序模板消息发送异常", e);
            JSONObject errObject = JSONObject.parseObject(e.getMessage());
            Integer errCode = (Integer) errObject.get(Constant.WECHAT_ERR_CODE);
            if (errCode != 41028 && errCode != 41029 && StringUtils.isNotEmpty(memberId)) {
                JSONObject jsonObject = JSONObject.parseObject(requestJsonStr);
                String formId = (String) jsonObject.get("form_id");
                this.insertXcxFormId(memberId, formId, formIdToDay);

                JSONObject outputObject = new JSONObject();
                outputObject.put("memberId", memberId);
                outputObject.put("formIdToDay", formIdToDay);
                outputObject.put("formId", formId);
                logger.error("发送小程序模板消息失败，formId重新插入到对应日期：{}", JSONObject.toJSONString(outputObject));
            }
            return false;
        }
    }

    /**
     * 发送公众号模板消息
     *
     * @param url            连接
     * @param requestJsonStr 模板消息请求参数Json字符串
     * @return 发送结果(true / false)
     */
    public boolean sendGzhMsg(String url, String requestJsonStr) {
        try {
            return this.send(url, requestJsonStr);
        } catch (Exception e) {
            logger.error("微信公众号模板消息发送异常：请求参数——" + requestJsonStr, e);
            return false;
        }
    }




    /**
     * 微信消息推送
     * @param isWrite 是否写入
     * @param content 消息内容
     */
    public void push(boolean isWrite,HashMap<String, Object> content){

        // 找到接受者的 openId
        List<String> openIdList = (List<String>) content.get("openIdList");
        String accessToken = (String) content.get("accessToken");
        String templateUrl = (String) content.get("templateUrl");
        String templateId = (String) content.get("templateId");

        // 提取发送的参数
        JSONObject jsonData = (JSONObject) content.get(Constant.WECHAT_NOTIFY_KEY);
        if (null == jsonData){
            throw new BusinessException("微信消息模板配置信息不存在");
        }
        String url = WechatConstant.POST_TEMPLATE_URL.replace(ACCESS_TOKEN, accessToken);
        for (String openId : openIdList){
            TemplateMessage templateMessage = new TemplateMessage();
            templateMessage.setData(jsonData);
            templateMessage.setTemplateId(templateId);
            templateMessage.setUrl(templateUrl);
            templateMessage.setTouser(openId);

            TemplateParameter templateParameter = new TemplateParameter();
            templateParameter.setTemplateMessage(templateMessage);
            templateParameter.setUrl(url);
            notifyPublisherService.send(templateParameter, Constant.MESSAGE_CHANNEL_WECHAT, isWrite);
        }
    }

    public void send(String openId){

        JSONObject jsonFirst = new JSONObject();
        jsonFirst.put("value", "您收到一笔巨款");
        jsonFirst.put("color", "#173177");

        JSONObject keynote1 = new JSONObject();
        keynote1.put("value", "众筹一次说走就走的旅行");
        keynote1.put("color", "#173177");

        JSONObject keynote2 = new JSONObject();
        keynote2.put("value", "微笑");
        keynote2.put("color", "#173177");

        JSONObject keynote3 = new JSONObject();
        keynote3.put("value", "1000万");
        keynote3.put("color", "#173177");

        JSONObject keynote4 = new JSONObject();
        keynote4.put("value", "2015年10月1日 20:30");
        keynote4.put("color", "#173177");

        JSONObject jsonRemark = new JSONObject();
        jsonRemark.put("value", "没条件支持你");
        jsonRemark.put("color", "#173177");

        JSONObject jsonData = new JSONObject();
        jsonData.put("first",jsonFirst);
        jsonData.put("keyword1",keynote1);
        jsonData.put("keyword2",keynote2);
        jsonData.put("keyword3",keynote3);
        jsonData.put("keyword4",keynote4);
        jsonData.put("remark",jsonRemark);

        String token = wechatOpenMemberService.getSystem().getAuthorizerAccessToken();
        String url = WechatConstant.POST_TEMPLATE_URL.replace(ACCESS_TOKEN, token);

        TemplateMessage templateMessage = new TemplateMessage();
        templateMessage.setTouser(openId);
        templateMessage.setUrl("4g.tongxingzhe.cn/micWeb");
        templateMessage.setTemplateId("IG2N0yWfkSRNba2DHjjHcr72DXOTUixCvOJ0anuhUto");
        templateMessage.setData(jsonData);
        this.sendGzhMsg(url, JSONObject.toJSONString(templateMessage));
    }

    /**
     * 微信小程序消息推送
     * @param isWrite 是否写入
     * @param content 消息内容
     */
    @Override
    public void pushXcxMessage(boolean isWrite, HashMap<String, Object> content) {
        // 找到接受者的 openId
        List<String> openIdList = (List<String>) content.get("openIdList");
        String accessToken = (String) content.get("accessToken");
        String templateUrl = (String) content.get("templateUrl");
        String templateId = (String) content.get("templateId");
        String formId = (String) content.get("formId");
        String memberId = (String) content.get("memberId");
        String formIdToDay = (String) content.get("formIdToDay");

        // 提取发送的参数
        JSONObject jsonData = (JSONObject) content.get(Constant.WECHAT_NOTIFY_KEY);
        if (null == jsonData) {
            throw new BusinessException("微信消息模板配置信息不存在");
        }
        String url = WechatConstant.MINI_PROGRAM_TEMPLATE_URL.replace(ACCESS_TOKEN, accessToken);
        for (String openId : openIdList) {
            XcxTemplateMessage templateMessage = new XcxTemplateMessage();
            templateMessage.setData(jsonData);
            templateMessage.setTemplateId(templateId);
            templateMessage.setPage(templateUrl);
            templateMessage.setFormId(formId);
            templateMessage.setTouser(openId);

            XcxTemplateParameter templateParameter = new XcxTemplateParameter();
            templateParameter.setXcxTemplateMessage(templateMessage);
            templateParameter.setUrl(url);
            templateParameter.setMemberId(memberId);
            templateParameter.setFormIdToDay(formIdToDay);
            logger.info("发送小程序模板消息内容：{}", JSONObject.toJSONString(templateMessage));
            notifyPublisherService.send(templateParameter, Constant.MESSAGE_CHANNEL_WECHAT_XCX, isWrite);
        }
    }

    public void sendXcxMsg() {
        JSONObject keynote1 = new JSONObject();
        keynote1.put("value", "有人喊你回来打卡啦");
        keynote1.put("color", "#173177");

        JSONObject keynote2 = new JSONObject();
        keynote2.put("value", "深圳湾打卡");
        keynote2.put("color", "#173177");

        JSONObject keynote3 = new JSONObject();
        keynote3.put("value", "24人在打卡，就差你了~立即打卡>>");
        keynote3.put("color", "#173177");

        JSONObject jsonData = new JSONObject();
        jsonData.put("keyword1", keynote1);
        jsonData.put("keyword2", keynote2);
        jsonData.put("keyword3", keynote3);


        String token = "7_XQSriojfYqrrWNyxc2Btf5Q5lkJKXEw-3mqX7lfsPpPUA_yFcuvvUmmlaC_p7-5uIn2vBpLqPkCgb7w5Kbsz-QTFSVvCrM7Y4a11zm75LEISS6sRuczqW_ZB9G8iDP4cjDcVmaTbWH1q9bqhQXHgAGABIS";
        String url = WechatConstant.MINI_PROGRAM_TEMPLATE_URL.replace(ACCESS_TOKEN, token);
        String openId = "oj_NF4xNq-zUyY-FL5diMbcMcNB4";
        String formId = "3f7d53b8478f2e55b648aa4000cb00ac";
        String page = "pages/index/index";
        String templateId = "BUc_pwKMB0XTIERaFl4glHar86H1tJiTr-soM7FFL8A";
        XcxTemplateMessage templateMessage = new XcxTemplateMessage();
        templateMessage.setTouser(openId);
        templateMessage.setPage(page);
        templateMessage.setFormId(formId);
        templateMessage.setTemplateId(templateId);
        templateMessage.setData(jsonData);

        XcxTemplateParameter templateParameter = new XcxTemplateParameter();
        templateParameter.setXcxTemplateMessage(templateMessage);
        templateParameter.setUrl(url);
        templateParameter.setMemberId("abc");
        templateParameter.setFormIdToDay("2018-03-20");
        this.sendXcxMsg(templateParameter);
    }

    /**
     * 存储formId
     * @param memberId 用户id
     * @param formId formId
     */
    public void insertXcxFormId(String memberId, String formId, String formIdToDay) {
        String today = DateUtils.formatDate(new Date(), DateUtils.DATE_PATTERN);
        if (StringUtils.isNotEmpty(formIdToDay)) {
            today = formIdToDay;
        }
        List<String> formIds = new LinkedList<String>();
        Map<String, List<String>> formDataMap = new LinkedHashMap<String, List<String>>();
        String jedisValue = stringJedis.getValue(REDIS_XCX_FORMID_LIST_KEY);
        if (StringUtils.isNotEmpty(jedisValue)) {
            JSONObject memberJsonObject = JSONObject.parseObject(jedisValue);
            Object date2FormData = memberJsonObject.get(memberId);
            if (date2FormData != null) {
                Object formIdData = ((JSONObject) date2FormData).get(today);
                if (formIdData != null) {
                    ((JSONArray) formIdData).add(formId);
                } else {
                    formIds.add(formId);
                    ((JSONObject) date2FormData).put(today, formIds);
                }
            } else {
                formIds.add(formId);
                formDataMap.put(today, formIds);
                memberJsonObject.put(memberId, formDataMap);
            }
            stringJedis.setValue(REDIS_XCX_FORMID_LIST_KEY, JSONObject.toJSONString(memberJsonObject));
        } else {
            formIds.add(formId);
            formDataMap.put(today, formIds);
            Map<String, Object> memberData = Maps.newHashMap();
            memberData.put(memberId, formDataMap);
            stringJedis.setValue(REDIS_XCX_FORMID_LIST_KEY, JSONObject.toJSONString(memberData));
        }
    }


    /**
     * 客服消息
     * @param touser 接受用户
     * @param file 文件
     * @param type 消息类型
     * @param accessToken 公众号令牌
     * @return 响应参数
     */
    @Override
    public boolean customerServiceSend(String touser,  String type, String accessToken,File file)throws Exception {
        String status = null;
        CustomRequest customRequest = null;
        CustomImage customImage = null;
        CustomText customText = null;

        // 图片,声音
        if(WechatConstant.TEMP_MEDIA_TYPE_IMAGE.equalsIgnoreCase(type) ||
                WechatConstant.TEMP_MEDIA_TYPE_VOICE.equalsIgnoreCase(type)
                ){
            //上传临时文件
            UploadTempMediaResponse utmr  =  wechatService.uploadTempMedia(file,accessToken,type);
            System.out.println("众筹成功海报推送_上传临时文件 "+"ErrCode="+utmr.getErrcode()+"___msg="+utmr.getErrmsg());
            logger.info("众筹成功海报推送_上传临时文件 ","ErrCode="+utmr.getErrcode()+"___msg="+utmr.getErrmsg());
            if(null==utmr || StringUtils.isBlank(utmr.getMediaId())){
                throw new IOException("MediaId为空,文件上传失败");
            }
            customImage = new CustomImage();
            customImage.setMediaId(utmr.getMediaId());

            customRequest = new CustomRequest();
            customRequest.setTouser(touser);
            customRequest.setMsgType(type);
            customRequest.setImage(customImage);
            //发送客服消息
            Response re= wechatService.customSend(customRequest,accessToken);
            status = re.getErrcode();
            System.out.println("众筹成功海报推送_发送客服消息 "+"ErrCode="+re.getErrcode()+"___msg="+re.getErrmsg());
            logger.info("众筹成功海报推送_发送客服消息 ","ErrCode="+re.getErrcode()+"___msg="+re.getErrmsg());
        }
        //文本
        else{

        }
        return "0".equals(status);
    }
}
